package com.ai.payment;

import com.ai.common.enums.SignType;
import com.ai.common.utils.TokenUtil;
import com.ai.sevice.ai.remote.CompletionsRequest;
import com.ai.sevice.ai.remote.CompletionsResponse;
import com.ai.sevice.ai.remote.Message;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import okhttp3.HttpUrl;
import org.apache.http.Header;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.*;

@Configuration
public class WxPayConfig {

    private static String configPath = WxPayConfig.class.getClassLoader().getResource("apiclient_key.pem").getPath();

    private static String merchantId = "1650284991";
    private static String merchantSerialNumber = "34752C0ECB334CFCAF0C8011ECF5787F67D771F3";
    private static String  apiV3Key= "shiningsoul15317983165zhenyouqu1";

    private PrivateKey getPrivateKey() throws IOException {
        String privateKey = "-----BEGIN PRIVATE KEY-----\n" +
                "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDoQjIaHTvsfec5\n" +
                "kZAquRnQxKqwaPgy1S9Wf5qNgiL2CbThBZ4Dr+QGNAC3okyaVBKCy03CbpG72gow\n" +
                "ofNYHX06oTOARmCExISmuhyA9b9n55GQpe+j+UlQLhRoiH8jDAAWixT4d53kZt5f\n" +
                "qZb0QajKhie6NT0YpvgIyxFweLTkAJO9l6uU+sCxVAab39aSlF8HrOKfqIyF6y48\n" +
                "gmb5JJuwwpVQ4DGgoW7fc4ab+oTTjMzME43bW9qbhTwioFzsBGVBRly6ZvxjOiHH\n" +
                "cZtFlm6gQpGdaR/wGu/+LAwDT5VWVmeA53OYIFYDgi+w7WGd2mUwoulVJU3qOZkd\n" +
                "aKP6gYGfAgMBAAECggEAMS3bGAZ6qs/aBymYYkOBgOAz2FjRvUnA1Ur9udsFdh2G\n" +
                "DGO5GsTCvsGCKWAXYlJM/R75XyM0fpdjsvqH4W+VFbYOhqngRBysjfU4leHzXpf9\n" +
                "DajlPk5JxM2NCrlkWlJvLlbS4O3LJBLYIV9ylFPW3tNbVCVzw2WPfaUqEyur+d7y\n" +
                "GCvEETZu2VDjPX52ffAL42/xWWd3T8wzrzuB4FOE3blQNIetVipiIzIR7158oFpO\n" +
                "jGqHELIZKjFDCEgYWkvm+lcfnenLNDMgym8d6A8yJBF1ItSJmp84JBs/vGCyGJul\n" +
                "yICFWZZ5j2FFm15t/4aquBa4KGbPMXSwym2laoBrkQKBgQD70xuXVmZc2dl7l0m8\n" +
                "71P1ldzVRn1ud4pdoofHuKxolGatqHU0hmedwcXSamJqjR1YhdZ4SQqiZYttdQyL\n" +
                "PkYfxxPdPKWmSySgfnP2/y2q/4S1GfdaeSbFH3eX8xj5OXfYa/lrY0l5D/5gSzc2\n" +
                "mm0IZOMBlr7N81ENPbTDJUIO+QKBgQDsHAm8Ov3WIWKpTVmSvXS7qE+DCfBGMZXm\n" +
                "ERMLgazYmfd5+F9xXQMToMPD2Ql24tGK/RwzkEQ8IoYispx/CzaoGEGNXQC4g17H\n" +
                "onbbGT9Feh6PmWv4gbsFRG/w8X1in7Sxk4zCdAtvwu0vJeGt+Z6AvJiNMyN8i/f7\n" +
                "jfiLNs2DVwKBgDRI3ZarWq92j8AoZifzLOR1jBc//nT8Ht9YCob+IdXI0hTGQCd6\n" +
                "rHLFs7P/YJWs3OXvS9tHlwymtq8wOT2D3X1lkQtDN0VynpUwDBXBX5L8YGpVjNTd\n" +
                "CJ6u7N7Am3PLacWmjW+teqjHGFKX60vL/k1a3QMMcGtEVJTCNhC6YJ/JAoGARY+N\n" +
                "HrOSjT+QvahYN28xsQfJRSXscAGz0/A72CwALGBQFNMj61YnzeSTSGPs8eWpLnWb\n" +
                "lWVvdPgG5LoSeStokuVyip9X0wSBK/elZK9vgJyV3GCq+q/d1ZNwF2BOPHwo1BhQ\n" +
                "ZAmkROz8y+MxNfxQwkTN/OuQDOV/zdDp5LnkmkkCgYEA9BJ+fA7dIzoYJXAPL3cQ\n" +
                "q639pzE4OIPRooy5qRl+UoGUwcj2guzXEJ2Dau9d+hMQIL2jPxNFtF16HCASwYrO\n" +
                "NWlQ8cUNeODdgJ8sJGk7inehVW9llQmiljT8A9wb9QJUvwD69huDIet+C0Aj6YNq\n" +
                "1xVWn/5U8HztTd413uW10bw=\n" +
                "-----END PRIVATE KEY-----\n";
        //return PemUtil.loadPrivateKey(Files.newInputStream(Paths.get(configPath)));
        return PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
    }

    @Bean
    public Verifier getVerifier() throws Exception {
        //获取商户私钥
        PrivateKey privateKey = getPrivateKey();
        //私钥签名对象
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(merchantSerialNumber, privateKey);
        //身份认证对象
        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(merchantId,privateKeySigner);
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(merchantId, wechatPay2Credentials, apiV3Key.getBytes(StandardCharsets.UTF_8));
        // ... 若有多个商户号，可继续调用putMerchant添加商户信息
        // 从证书管理器中获取verifier
        return certificatesManager.getVerifier(merchantId);
    }

    @Bean
    public CloseableHttpClient getWxPayClient(Verifier verifier) throws Exception {
        //获取商户私钥
        PrivateKey privateKey = getPrivateKey();
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(merchantId, merchantSerialNumber,privateKey)
                .withValidator(new WechatPay2Validator(verifier));
        // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient
        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签，并进行证书自动更新
        return builder.build();
    }


    public static void main(String[] args) throws Exception {
        //创建订单
        createOrder2();
        //参数解密
        decrypt();

    }

    public static String schema = "WECHATPAY2-SHA256-RSA2048";
    public static HttpUrl httpurl = HttpUrl.parse("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
    public static String getToken(String method, String url, String body) throws Exception {
        String nonceStr = UUID.randomUUID().toString();
        HttpUrl httpurl = HttpUrl.parse(url);
        long timestamp = System.currentTimeMillis() / 1000;
        String message = buildMessage(method, httpurl, timestamp, nonceStr, body);
        String signature = sign(message.getBytes("utf-8"));
        return "mchid=\"" + merchantId + "\","
                + "nonce_str=\"" + nonceStr + "\","
                + "timestamp=\"" + timestamp + "\","
                + "serial_no=\"" + merchantSerialNumber + "\","
                + "signature=\"" + signature + "\"";
    }
    public static String sign(byte[] message) throws Exception {
        //获取商户私钥
        PrivateKey privateKey = new WxPayConfig().getPrivateKey();
        Signature sign = Signature.getInstance("SHA256withRSA");
        sign.initSign(privateKey);
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    public static String buildMessage(String method, HttpUrl url, long timestamp, String nonceStr, String body) {
        String canonicalUrl = url.encodedPath();
        if (url.encodedQuery() != null) {
            canonicalUrl += "?" + url.encodedQuery();
        }
        return method + "\n"
                + canonicalUrl + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + body + "\n";
    }

    private static void decrypt() throws GeneralSecurityException {
        AesUtil aes = new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8));
        String ciphertext = "e771kwT1i4eY5DJQZ4/mxuNYJ9n7s9IqF7CDd2SPDpje0IPbdX1kZBbPipL4VjqWtH+nmZu+qmcEC9HyHmbvDFIOds8zjx7cOOpH+4ohzmcDTyMQLhoOAuGaXb/yLGKJIL4X5pekU9dmV5pRe3uVy5AK/8HC/mvgoUvO6WeWtmSC7D2NNQ1XOqys8Ux0yRM0wgjFY5MYcVMeN1WMdc/XgQrR0vNyxtVlLx3fMk7858Nb0EbWGznWTAyVZV1HRj8o9bSPVPY+7VEaRj069KXi1zrFIuWKDZm5pI/mU1jXwagBSJoYrbgH5VeXzHNAtxIEZWAscLIGzcotZQ4RrokErz0f2y6/WZhmKwVbbqA8O9Ede/bFZl0Icr+msjHkpoQ0CI0SJ3JaH88b7Pm4K/9iqdaHIicaXTPd9JRIXF8QwnP+3itT39wYBgxnf+7eiAhVFgmRndUMBlIxF3u62GM/BIHmf6e9FXKOF9bIUWn3xkW3NgCwB85X1/DcQ0YX5XvbHMCy40H4hMXg+Lv41tmoesScTEprd5+1wGjXJptGmhWFIX9mu4LZ1OUk+jI=";
        String associated_data = "transaction";
        String nonce = "Whk3RPB2Ee5b";
        String decryptToString = aes.decryptToString(associated_data.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), ciphertext);
        System.out.println(decryptToString);
    }

    private static void createOrder2() throws Exception {
        String urlStr = "https://api.mch.weixin.qq.com/v3/pay/transactions/native";
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders head = new HttpHeaders();
        head.add("Accept", "application/json");
        head.add("Content-type","application/json; charset=utf-8");

        Map<String,Object> map = new HashMap<>();
        map.put("mchid","1650284991");
        map.put("description", "真有趣商品测试");
        map.put("appid", "wx59a2176b7a30d670");
        map.put("notify_url", "https://www.epochai.top/ai/payment/wxPayNotify");
        map.put("out_trade_no", "P" + System.currentTimeMillis());
        Map<String,Object> amountMap = new HashMap<>();
        amountMap.put("total", 1);
        map.put("amount",amountMap);
        String body = JSON.toJSONString(map);
        System.out.println("请求body -> " + body);
        String token = getToken("POST", urlStr, body);

        String authorization =  schema + " " + token;
        head.add("Authorization", authorization);

        HttpEntity<Map<String,Object>> entity = new HttpEntity<>(map,head);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(urlStr, entity, String.class,new HashMap<>());
        System.out.println(responseEntity.getBody());

    }
    private static void createOrder() throws Exception {
        WxPayConfig config = new WxPayConfig();
        CloseableHttpClient wxPayClient = config.getWxPayClient(config.getVerifier());
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/native");
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");
        Map<String,Object> map = new HashMap<>();
        map.put("mchid","1650284991");
        map.put("appid", "wx59a2176b7a30d670");
        map.put("description", "真有趣商品测试");
        map.put("notify_url", "https://www.epochai.top/ai/payment/wxPayNotify");
        map.put("out_trade_no", "P" + System.currentTimeMillis());
        Map<String,Object> amountMap = new HashMap<>();
        amountMap.put("total", 1);
        map.put("amount",amountMap);

        httpPost.setEntity(new StringEntity(JSON.toJSONString(map), "UTF-8"));
        CloseableHttpResponse response = wxPayClient.execute(httpPost);
        Header[] allHeaders = response.getAllHeaders();

        String bodyAsString = EntityUtils.toString(response.getEntity());
        System.out.println("=============================================");
        for (Header header : allHeaders) {
            System.out.println(header.getName() + ":" + header.getValue());
        }
        System.out.println("=============================================");
        System.out.println(bodyAsString);
        System.out.println("=============================================");
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200){
            //处理成功 有body
            System.out.println("处理成功 有body");
        }else if (statusCode == 204){
            //处理成功 没有body
            System.out.println("处理成功 没有body");
        }else{
            //处理失败
            System.out.println("处理失败");
        }
    }




//    public static String createSign(Map<String, String> params, String partnerKey, SignType signType) {
//        List<String> keys = new ArrayList(params.keySet());
//        Collections.sort(keys);
//        StringBuilder content = new StringBuilder();
//
//        for(int i = 0; i < keys.size(); ++i) {
//            String key = (String)keys.get(i);
//            String value = (String)params.get(key);
//            if (i == keys.size() - 1) {
//                content.append(key).append("=").append(urlEncode(value));
//            } else {
//                content.append(key).append("=").append('"').append(urlEncode(value)).append('"').append("&");
//            }
//        }
//
//        String stringSignTemp = content.toString() + "&key=" + partnerKey;
//        String sign = signType == SignType.MD5 ? SecureUtil.md5(stringSignTemp).toUpperCase() : hmacSha256(stringSignTemp, partnerKey).toUpperCase();
//        return sign;
//    }
//    public static String urlEncode(String src) {
//        try {
//            return URLEncoder.encode(src, "UTF-8").replace("+", "%20");
//        } catch (UnsupportedEncodingException var2) {
//            var2.printStackTrace();
//            return null;
//        }
//    }


}
